"""
主窗口界面模块 - 完整修复版本
负责管理主界面和协调各个功能模块
"""

import tkinter as tk
from tkinter import ttk, messagebox, simpledialog, filedialog
import threading
import time
import queue
import os
import logging
from typing import List, Tuple, Optional, Dict, Any
from datetime import datetime

from core.point_manager import PointManager, Point
from core.automation_executor import AutomationExecutor
from core.image_processor import ImageProcessor
from core.config_manager import ConfigManager
from core.excel_handler import ExcelHandler
from ui.excel_tool import ExcelToolWindow
from ui.components.point_editor import PointEditorDialog
from ui.components.config_dialog import ConfigDialog

logger = logging.getLogger(__name__)


class MainWindow:
    """主窗口类 - 完整修复版本"""

    def __init__(self, root: tk.Tk, config_manager: ConfigManager):
        self.root = root
        self.config_manager = config_manager
        self.config = config_manager.load_config()

        # 初始化核心模块
        self.point_manager = PointManager()
        self.image_processor = ImageProcessor()
        self.automation_executor = AutomationExecutor(self.point_manager, self.image_processor)
        self.excel_handler = ExcelHandler()

        # 状态变量
        self.is_recording = False
        self.is_executing = False
        self.is_excel_executing = False
        self.excel_data = None

        # 线程通信队列
        self.status_queue = queue.Queue()

        # Excel工具窗口
        self.excel_tool_window = None

        # 快捷键绑定
        self.keyboard_listener = None

        # 设置窗口
        self.setup_window()
        self.create_widgets()
        self.apply_config()
        self.bind_events()

        # 启动状态更新循环
        self.process_status_queue()

    def setup_window(self):
        """设置窗口属性 - 修复版本"""
        self.root.title("屏幕点击和输入工具 - 优化版 v2.0")
        self.root.geometry("700x650")
        self.root.minsize(600, 550)

        # 设置窗口图标
        try:
            icon_path = self.get_resource_path("assets/icon.ico")
            if icon_path and os.path.exists(icon_path):
                self.root.iconbitmap(icon_path)
        except Exception as e:
            logger.debug(f"设置窗口图标失败: {e}")

        # 设置窗口位置
        window_position = self.config.get('window_position')
        if window_position:
            try:
                self.root.geometry(f"+{window_position[0]}+{window_position[1]}")
            except:
                pass

    def get_resource_path(self, relative_path: str) -> str:
        """获取资源文件路径"""
        try:
            import sys
            base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
            return os.path.join(base_path, relative_path)
        except:
            return relative_path

    def create_widgets(self):
        """创建界面组件 - 修复版本"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 创建笔记本（选项卡）
        self.notebook = ttk.Notebook(main_frame)
        self.notebook.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 创建主要选项卡
        self.main_tab = ttk.Frame(self.notebook, padding="5")
        self.config_tab = ttk.Frame(self.notebook, padding="5")

        self.notebook.add(self.main_tab, text="主要功能")
        self.notebook.add(self.config_tab, text="高级配置")

        # 在主选项卡中创建组件
        self.create_main_tab_widgets(self.main_tab)

        # 在配置选项卡中创建组件
        self.create_config_tab_widgets(self.config_tab)

        # 创建状态栏
        self.create_status_bar(main_frame)

    def create_main_tab_widgets(self, parent):
        """创建主选项卡组件"""
        # 顶部控制区域
        self.create_top_controls(parent)

        # 点列表显示区域
        self.create_points_display(parent)

        # 操作按钮区域
        self.create_action_buttons(parent)

    def create_config_tab_widgets(self, parent):
        """创建配置选项卡组件"""
        # 基本配置区域
        basic_config_frame = ttk.LabelFrame(parent, text="基本设置", padding="10")
        basic_config_frame.pack(fill=tk.X, pady=(0, 10))

        self.create_basic_config_section(basic_config_frame)

        # 高级配置区域
        advanced_config_frame = ttk.LabelFrame(parent, text="高级设置", padding="10")
        advanced_config_frame.pack(fill=tk.BOTH, expand=True)

        self.create_advanced_config_section(advanced_config_frame)

    def create_top_controls(self, parent):
        """创建顶部控制区域 - 修复版本"""
        top_frame = ttk.Frame(parent)
        top_frame.pack(fill=tk.X, pady=(0, 10))

        # 左侧：窗口控制
        left_frame = ttk.Frame(top_frame)
        left_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 置顶选项
        self.always_on_top_var = tk.BooleanVar(value=self.config.get('always_on_top', True))
        topmost_check = ttk.Checkbutton(
            left_frame,
            text="窗口始终置顶",
            variable=self.always_on_top_var,
            command=self.toggle_topmost
        )
        topmost_check.pack(side=tk.LEFT)

        # 自动保存配置
        self.auto_save_var = tk.BooleanVar(value=self.config.get('auto_save_config', True))
        auto_save_check = ttk.Checkbutton(
            left_frame,
            text="自动保存配置",
            variable=self.auto_save_var,
            command=self.toggle_auto_save
        )
        auto_save_check.pack(side=tk.LEFT, padx=(20, 0))

        # 右侧：操作按钮
        right_frame = ttk.Frame(top_frame)
        right_frame.pack(side=tk.RIGHT)

        # 记录点按钮
        self.record_btn = ttk.Button(
            right_frame,
            text="记录点 (Ctrl+R)",
            command=self.start_recording
        )
        self.record_btn.pack(side=tk.LEFT, padx=(10, 0))

        # 导入/导出按钮
        import_export_frame = ttk.Frame(right_frame)
        import_export_frame.pack(side=tk.LEFT, padx=(10, 0))

        ttk.Button(
            import_export_frame,
            text="导入点",
            command=self.import_points,
            width=8
        ).pack(side=tk.LEFT, padx=(0, 2))

        ttk.Button(
            import_export_frame,
            text="导出点",
            command=self.export_points,
            width=8
        ).pack(side=tk.LEFT)

    def create_points_display(self, parent):
        """创建点列表显示区域 - 修复版本"""
        points_frame = ttk.LabelFrame(parent, text="已记录的点", padding="5")
        points_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 创建Treeview和滚动条容器
        tree_frame = ttk.Frame(points_frame)
        tree_frame.pack(fill=tk.BOTH, expand=True)

        # 创建Treeview
        columns = ("序号", "坐标", "输入内容", "点击类型", "延迟", "状态", "描述")
        self.points_treeview = ttk.Treeview(
            tree_frame,
            columns=columns,
            show="headings",
            height=8,
            selectmode="extended"  # 支持多选
        )

        # 设置列
        column_configs = {
            "序号": {"width": 50, "anchor": "center"},
            "坐标": {"width": 100, "anchor": "center"},
            "输入内容": {"width": 150, "anchor": "w"},
            "点击类型": {"width": 80, "anchor": "center"},
            "延迟": {"width": 60, "anchor": "center"},
            "状态": {"width": 50, "anchor": "center"},
            "描述": {"width": 120, "anchor": "w"}
        }

        for col in columns:
            self.points_treeview.heading(col, text=col)
            config = column_configs.get(col, {})
            self.points_treeview.column(col,
                                      width=config.get("width", 100),
                                      anchor=config.get("anchor", "w"))

        # 滚动条
        scrollbar = ttk.Scrollbar(tree_frame, orient=tk.VERTICAL, command=self.points_treeview.yview)
        self.points_treeview.configure(yscrollcommand=scrollbar.set)

        # 布局
        self.points_treeview.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 点操作按钮框架
        point_ops_frame = ttk.Frame(points_frame)
        point_ops_frame.pack(fill=tk.X, pady=(5, 0))

        # 左侧：点配置
        config_frame = ttk.Frame(point_ops_frame)
        config_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 点击类型选择
        ttk.Label(config_frame, text="点击类型:").pack(side=tk.LEFT, padx=(0, 5))
        self.click_type_var = tk.StringVar(value=self.config.get('click_type', '单击'))
        click_type_combo = ttk.Combobox(
            config_frame,
            textvariable=self.click_type_var,
            values=["单击", "双击", "右键点击"],
            state="readonly",
            width=10
        )
        click_type_combo.pack(side=tk.LEFT, padx=(0, 10))
        click_type_combo.bind('<<ComboboxSelected>>', self.on_click_type_changed)

        # 延迟设置
        ttk.Label(config_frame, text="延迟(秒):").pack(side=tk.LEFT, padx=(0, 5))
        self.delay_after_var = tk.StringVar(value=str(self.config.get('delay_after', 0.5)))
        delay_entry = ttk.Entry(config_frame, textvariable=self.delay_after_var, width=6)
        delay_entry.pack(side=tk.LEFT, padx=(0, 10))
        delay_entry.bind('<FocusOut>', self.on_delay_changed)

        # 右侧：点操作按钮
        btn_frame = ttk.Frame(point_ops_frame)
        btn_frame.pack(side=tk.RIGHT)

        ttk.Button(btn_frame, text="编辑点", command=self.edit_point).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="启用/禁用", command=self.toggle_selected_points).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="上移", command=self.move_point_up).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="下移", command=self.move_point_down).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="复制", command=self.duplicate_point).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="删除", command=self.delete_selected_points).pack(side=tk.LEFT, padx=2)

    def create_action_buttons(self, parent):
        """创建操作按钮区域 - 修复版本"""
        btn_frame = ttk.LabelFrame(parent, text="操作控制", padding="10")
        btn_frame.pack(fill=tk.X, pady=(0, 10))

        # 第一行：主要操作按钮
        row1 = ttk.Frame(btn_frame)
        row1.pack(fill=tk.X, pady=2)

        self.execute_btn = ttk.Button(
            row1,
            text="执行所有操作 (Ctrl+E)",
            command=self.start_execution,
            state=tk.DISABLED
        )
        self.execute_btn.pack(side=tk.LEFT, padx=2)

        self.stop_btn = ttk.Button(
            row1,
            text="停止执行 (Ctrl+S)",
            command=self.stop_execution,
            state=tk.DISABLED
        )
        self.stop_btn.pack(side=tk.LEFT, padx=2)

        ttk.Button(row1, text="测试输入", command=self.test_input).pack(side=tk.LEFT, padx=2)
        ttk.Button(row1, text="Excel工具", command=self.open_excel_tool).pack(side=tk.LEFT, padx=2)

        # 第二行：Excel操作按钮
        row2 = ttk.Frame(btn_frame)
        row2.pack(fill=tk.X, pady=2)

        self.excel_execute_btn = ttk.Button(
            row2,
            text="执行Excel数据",
            command=self.start_excel_execution,
            state=tk.DISABLED
        )
        self.excel_execute_btn.pack(side=tk.LEFT, padx=2)

        self.stop_excel_btn = ttk.Button(
            row2,
            text="停止Excel执行",
            command=self.stop_excel_execution,
            state=tk.DISABLED
        )
        self.stop_excel_btn.pack(side=tk.LEFT, padx=2)

        ttk.Button(row2, text="验证所有点", command=self.validate_all_points).pack(side=tk.LEFT, padx=2)
        ttk.Button(row2, text="点统计", command=self.show_points_statistics).pack(side=tk.LEFT, padx=2)

    def create_basic_config_section(self, parent):
        """创建基本配置区域"""
        # 输入方式配置
        input_frame = ttk.Frame(parent)
        input_frame.pack(fill=tk.X, pady=2)

        ttk.Label(input_frame, text="输入方式:").pack(side=tk.LEFT)
        self.input_method_var = tk.StringVar(value=self.config.get('input_method', 'paste'))

        ttk.Radiobutton(input_frame, text="粘贴方式", variable=self.input_method_var, value="paste").pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(input_frame, text="键盘方式", variable=self.input_method_var, value="keyboard").pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(input_frame, text="图片输入", variable=self.input_method_var, value="image").pack(side=tk.LEFT, padx=5)

        # 图片选择按钮
        self.image_btn = ttk.Button(input_frame, text="选择图片", command=self.select_image)
        self.image_btn.pack(side=tk.RIGHT, padx=5)

        # 更新图片按钮状态
        self.update_image_button_state()

        # 输入选项
        options_frame = ttk.Frame(parent)
        options_frame.pack(fill=tk.X, pady=2)

        self.clear_before_input = tk.BooleanVar(value=self.config.get('clear_before_input', True))
        ttk.Checkbutton(options_frame, text="输入前清除内容", variable=self.clear_before_input).pack(side=tk.LEFT, padx=5)

        self.enter_after_input = tk.BooleanVar(value=self.config.get('enter_after_input', False))
        ttk.Checkbutton(options_frame, text="输入后按回车", variable=self.enter_after_input).pack(side=tk.LEFT, padx=5)

        self.stop_on_error = tk.BooleanVar(value=self.config.get('stop_on_error', True))
        ttk.Checkbutton(options_frame, text="出错时停止", variable=self.stop_on_error).pack(side=tk.LEFT, padx=5)

        # 全局设置
        global_frame = ttk.Frame(parent)
        global_frame.pack(fill=tk.X, pady=2)

        ttk.Label(global_frame, text="全局延迟(秒):").pack(side=tk.LEFT)
        self.global_delay_var = tk.StringVar(value=str(self.config.get('global_delay', 3)))
        global_delay_entry = ttk.Entry(global_frame, textvariable=self.global_delay_var, width=5)
        global_delay_entry.pack(side=tk.LEFT, padx=(0, 10))
        global_delay_entry.bind('<FocusOut>', self.validate_numeric_inputs)

        ttk.Label(global_frame, text="全局间隔(秒):").pack(side=tk.LEFT)
        self.global_interval_var = tk.StringVar(value=str(self.config.get('global_interval', 0.5)))
        global_interval_entry = ttk.Entry(global_frame, textvariable=self.global_interval_var, width=5)
        global_interval_entry.pack(side=tk.LEFT, padx=(0, 10))
        global_interval_entry.bind('<FocusOut>', self.validate_numeric_inputs)

    def create_advanced_config_section(self, parent):
        """创建高级配置区域"""
        # 使用文本框显示和编辑高级配置
        config_text_frame = ttk.Frame(parent)
        config_text_frame.pack(fill=tk.BOTH, expand=True)

        ttk.Label(config_text_frame, text="高级配置 (JSON格式):").pack(anchor=tk.W, pady=(0, 5))

        # 配置文本框和滚动条
        text_frame = ttk.Frame(config_text_frame)
        text_frame.pack(fill=tk.BOTH, expand=True)

        self.config_text = tk.Text(text_frame, wrap=tk.WORD, width=60, height=15)
        scrollbar = ttk.Scrollbar(text_frame, orient=tk.VERTICAL, command=self.config_text.yview)
        self.config_text.configure(yscrollcommand=scrollbar.set)

        self.config_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 加载当前配置到文本框
        self.load_config_to_text()

        # 操作按钮
        config_btn_frame = ttk.Frame(config_text_frame)
        config_btn_frame.pack(fill=tk.X, pady=(5, 0))

        ttk.Button(config_btn_frame, text="刷新配置", command=self.load_config_to_text).pack(side=tk.LEFT, padx=2)
        ttk.Button(config_btn_frame, text="验证配置", command=self.validate_config_text).pack(side=tk.LEFT, padx=2)
        ttk.Button(config_btn_frame, text="应用配置", command=self.apply_config_text).pack(side=tk.LEFT, padx=2)
        ttk.Button(config_btn_frame, text="重置配置", command=self.reset_config_text).pack(side=tk.LEFT, padx=2)

    def create_status_bar(self, parent):
        """创建状态栏 - 修复版本"""
        status_frame = ttk.Frame(parent)
        status_frame.pack(fill=tk.X, side=tk.BOTTOM)

        # 状态消息
        self.status_var = tk.StringVar(value="就绪")
        status_label = ttk.Label(
            status_frame,
            textvariable=self.status_var,
            relief=tk.SUNKEN,
            anchor=tk.W,
            padding=(5, 2)
        )
        status_label.pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 点计数
        self.points_count_var = tk.StringVar(value="点数: 0")
        points_label = ttk.Label(
            status_frame,
            textvariable=self.points_count_var,
            relief=tk.SUNKEN,
            anchor=tk.E,
            padding=(5, 2),
            width=15
        )
        points_label.pack(side=tk.RIGHT)

        # 更新点计数
        self.update_points_count()

    def bind_events(self):
        """绑定事件 - 修复版本"""
        # 快捷键
        self.root.bind('<Control-r>', lambda e: self.start_recording())
        self.root.bind('<Control-e>', lambda e: self.start_execution())
        self.root.bind('<Control-s>', lambda e: self.stop_execution())
        self.root.bind('<Delete>', lambda e: self.delete_selected_points())
        self.root.bind('<F1>', lambda e: self.show_help())

        # 窗口事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.root.bind('<Configure>', self.on_window_move)

        # Treeview事件
        self.points_treeview.bind('<Double-1>', lambda e: self.edit_point())
        self.points_treeview.bind('<<TreeviewSelect>>', self.on_point_selection_changed)

    def apply_config(self):
        """应用配置"""
        self.root.attributes('-topmost', self.always_on_top_var.get())
        self.update_image_button_state()

    def toggle_topmost(self):
        """切换置顶状态"""
        self.root.attributes('-topmost', self.always_on_top_var.get())

    def toggle_auto_save(self):
        """切换自动保存"""
        # 自动保存设置会立即生效
        pass

    def update_image_button_state(self):
        """更新图片按钮状态"""
        if self.input_method_var.get() == "image":
            self.image_btn.config(state=tk.NORMAL)
        else:
            self.image_btn.config(state=tk.DISABLED)

    def on_click_type_changed(self, event=None):
        """点击类型改变事件"""
        selection = self.points_treeview.selection()
        if selection:
            # 更新选中点的点击类型
            for item in selection:
                index = self.points_treeview.index(item)
                success, message = self.point_manager.update_point(
                    index,
                    click_type=self.click_type_var.get()
                )
                if not success:
                    self.show_error(f"更新点失败: {message}")

            self.update_points_display()

    def on_delay_changed(self, event=None):
        """延迟设置改变事件"""
        try:
            delay = float(self.delay_after_var.get())
            if delay < 0 or delay > 60:
                raise ValueError("延迟必须在0-60秒之间")

            selection = self.points_treeview.selection()
            if selection:
                # 更新选中点的延迟
                for item in selection:
                    index = self.points_treeview.index(item)
                    success, message = self.point_manager.update_point(
                        index,
                        delay_after=delay
                    )
                    if not success:
                        self.show_error(f"更新点失败: {message}")

                self.update_points_display()

        except ValueError as e:
            self.show_error(f"延迟设置无效: {e}")
            # 恢复默认值
            self.delay_after_var.set(str(self.config.get('delay_after', 0.5)))

    def validate_numeric_inputs(self, event=None):
        """验证数值输入"""
        try:
            global_delay = float(self.global_delay_var.get())
            if global_delay < 0 or global_delay > 300:
                raise ValueError("全局延迟必须在0-300秒之间")
        except ValueError:
            self.show_error("全局延迟必须是0-300之间的数字")
            self.global_delay_var.set(str(self.config.get('global_delay', 3)))

        try:
            global_interval = float(self.global_interval_var.get())
            if global_interval < 0 or global_interval > 60:
                raise ValueError("全局间隔必须在0-60秒之间")
        except ValueError:
            self.show_error("全局间隔必须是0-60之间的数字")
            self.global_interval_var.set(str(self.config.get('global_interval', 0.5)))

    def load_config_to_text(self):
        """加载配置到文本框"""
        try:
            import json
            config = self.config_manager.load_config()
            formatted_config = json.dumps(config, ensure_ascii=False, indent=2)
            self.config_text.delete(1.0, tk.END)
            self.config_text.insert(1.0, formatted_config)
        except Exception as e:
            self.show_error(f"加载配置到文本框失败: {e}")

    def validate_config_text(self):
        """验证配置文本"""
        try:
            import json
            config_text = self.config_text.get(1.0, tk.END).strip()
            config = json.loads(config_text)

            is_valid, errors = self.config_manager.validate_config(config)
            if is_valid:
                self.show_info("配置格式正确")
            else:
                self.show_error(f"配置验证失败:\n" + "\n".join(errors))

        except json.JSONDecodeError as e:
            self.show_error(f"JSON格式错误: {e}")
        except Exception as e:
            self.show_error(f"验证配置失败: {e}")

    def apply_config_text(self):
        """应用文本框中的配置"""
        try:
            import json
            config_text = self.config_text.get(1.0, tk.END).strip()
            config = json.loads(config_text)

            if self.config_manager.save_config(config):
                self.config = config
                self.apply_config()
                self.show_info("配置已应用并保存")
            else:
                self.show_error("配置保存失败")

        except json.JSONDecodeError as e:
            self.show_error(f"JSON格式错误: {e}")
        except Exception as e:
            self.show_error(f"应用配置失败: {e}")

    def reset_config_text(self):
        """重置配置文本"""
        if messagebox.askyesno("确认", "确定要重置为默认配置吗？"):
            self.config_manager.reset_config()
            self.config = self.config_manager.load_config()
            self.load_config_to_text()
            self.apply_config()
            self.show_info("配置已重置")

    def update_points_count(self):
        """更新点计数"""
        total_points = self.point_manager.get_point_count()
        enabled_points = self.point_manager.get_enabled_point_count()
        self.points_count_var.set(f"点数: {enabled_points}/{total_points}")

    def on_window_move(self, event=None):
        """窗口移动事件"""
        if event.widget == self.root:
            # 保存窗口位置
            x = self.root.winfo_x()
            y = self.root.winfo_y()
            self.config['window_position'] = [x, y]

            # 自动保存配置
            if self.auto_save_var.get():
                self.save_config()

    def on_point_selection_changed(self, event=None):
        """点选择改变事件"""
        selection = self.points_treeview.selection()
        if len(selection) == 1:
            # 单点选择，更新配置控件
            item = selection[0]
            index = self.points_treeview.index(item)
            point = self.point_manager.get_point(index)
            if point:
                self.click_type_var.set(point.click_type)
                self.delay_after_var.set(str(point.delay_after))

    def process_status_queue(self):
        """处理状态队列（线程安全的状态更新）"""
        try:
            while True:
                try:
                    message = self.status_queue.get_nowait()
                    self.status_var.set(message)
                except queue.Empty:
                    break
        except Exception as e:
            logger.error(f"处理状态队列失败: {e}")

        # 继续调度
        self.root.after(100, self.process_status_queue)

    def update_status(self, message: str):
        """更新状态（线程安全）"""
        try:
            self.status_queue.put(message)
        except:
            # 如果队列已满，直接更新
            self.root.after(0, lambda: self.status_var.set(message))

    def start_recording(self):
        """开始记录点 - 修复版本"""
        if self.is_recording:
            return

        # 检查必要的依赖
        if not self._check_recording_dependencies():
            return

        self.is_recording = True
        self.record_btn.config(state=tk.DISABLED)
        self.update_status("记录模式启动中...")

        # 在新线程中执行记录
        thread = threading.Thread(target=self._recording_thread, daemon=True)
        thread.start()

    def _recording_thread(self):
        """记录点的线程函数 - 修复版本"""
        try:
            import pyautogui
            import keyboard

            # 在主线程中显示提示信息
            self.root.after(0, lambda: messagebox.showinfo(
                "提示",
                "将鼠标移动到目标位置后按空格键记录点。\n按ESC键退出记录模式。\n\n注意：记录期间程序窗口会最小化。"
            ))

            # 等待提示框显示
            time.sleep(1)

            # 最小化窗口
            self.root.after(0, self.root.iconify)

            # 记录点计数器
            point_count = 0

            # 键盘事件监听
            def on_space(event):
                nonlocal point_count
                if event.event_type == keyboard.KEY_DOWN and event.name == 'space':
                    # 获取当前鼠标位置
                    x, y = pyautogui.position()

                    # 在主线程中处理记录点
                    self.root.after(0, lambda: self._process_recorded_point(x, y))
                    point_count += 1

            def on_esc(event):
                if event.event_type == keyboard.KEY_DOWN and event.name == 'esc':
                    # 停止监听
                    keyboard.unhook_all()
                    # 停止记录
                    self.root.after(0, self._stop_recording)

            # 注册键盘监听
            keyboard.hook_key('space', on_space)
            keyboard.hook_key('esc', on_esc)

            # 更新状态
            self.update_status("记录模式已启动 - 按空格记录点，ESC退出")

            # 保持线程运行，直到记录停止
            while self.is_recording:
                time.sleep(0.1)

        except ImportError as e:
            self.show_error(f"记录功能初始化失败: {str(e)}")
        except Exception as e:
            self.show_error(f"记录过程中出错: {e}")
        finally:
            # 确保清理键盘监听
            try:
                import keyboard
                keyboard.unhook_all()
            except:
                pass
            self._stop_recording()

    def _process_recorded_point(self, x, y):
        """处理记录的点坐标 - 修复版本"""
        try:
            # 根据输入方式询问内容
            if self.input_method_var.get() == "image":
                # 如果是图片输入模式，使用当前选择的图片
                if not self.image_processor.is_image_loaded():
                    self.show_warning("请先选择图片")
                    return
                text = self.image_processor.current_image_path
                is_image = True
                description = f"图片: {os.path.basename(text)}"
            else:
                # 普通文本输入
                text = simpledialog.askstring(
                    "输入文字",
                    f"坐标: ({x}, {y})\n如果需要在此位置输入文字，请输入内容:\n(留空表示只点击不输入)",
                    parent=self.root
                )
                is_image = False
                description = ""

            # 用户取消输入
            if text is None:
                return

            # 使用当前选择的点击类型和延迟
            click_type = self.click_type_var.get()
            try:
                delay_after = float(self.delay_after_var.get())
            except:
                delay_after = 0.5

            # 添加点到列表
            success, message = self.point_manager.add_point(
                x, y, text or "", click_type, delay_after, is_image, description
            )

            if success:
                # 更新显示
                self.update_points_display()
                self.update_status(f"已记录点 ({x}, {y}) - 总点数: {self.point_manager.get_point_count()}")
            else:
                self.show_error(f"记录点失败: {message}")

        except Exception as e:
            self.show_error(f"处理记录点时出错: {e}")

    def _stop_recording(self):
        """停止记录 - 修复版本"""
        self.is_recording = False

        # 恢复界面状态
        self.root.after(0, lambda: self.record_btn.config(state=tk.NORMAL))
        self.root.after(0, self.root.deiconify)
        self.update_status("记录模式已结束")

    def update_points_display(self):
        """更新点列表显示 - 修复版本"""
        # 清空现有显示
        for item in self.points_treeview.get_children():
            self.points_treeview.delete(item)

        # 添加所有点
        points = self.point_manager.get_all_points()
        for i, point_tuple in enumerate(points):
            # 解析点数据
            if len(point_tuple) >= 6:
                x, y, text, click_type, delay_after, is_image = point_tuple[:6]
                description = point_tuple[6] if len(point_tuple) > 6 else ""
                enabled = point_tuple[7] if len(point_tuple) > 7 else True

                display_text = f"[图片] {os.path.basename(text)}" if is_image else text
                status = "启用" if enabled else "禁用"

                self.points_treeview.insert(
                    "", "end",
                    values=(i + 1, f"({x}, {y})", display_text, click_type,
                           f"{delay_after}秒", status, description)
                )

        # 更新执行按钮状态
        has_points = len(points) > 0
        state = tk.NORMAL if has_points else tk.DISABLED
        self.execute_btn.config(state=state)

        # 更新点计数
        self.update_points_count()

    def edit_point(self):
        """编辑点 - 修复版本"""
        selection = self.points_treeview.selection()
        if not selection:
            self.show_warning("请先选择一个点")
            return

        # 只编辑第一个选中的点
        item = selection[0]
        index = self.points_treeview.index(item)
        point = self.point_manager.get_point(index)
        if not point:
            self.show_error("点不存在")
            return

        # 创建编辑对话框
        dialog = PointEditorDialog(self.root, point, self.image_processor)
        if dialog.result:
            success, message = self.point_manager.update_point(index, **dialog.result)
            if success:
                self.update_points_display()
                self.show_info("点已更新")
            else:
                self.show_error(f"更新点失败: {message}")

    def toggle_selected_points(self):
        """切换选中点的启用状态"""
        selection = self.points_treeview.selection()
        if not selection:
            self.show_warning("请先选择点")
            return

        for item in selection:
            index = self.points_treeview.index(item)
            success, message = self.point_manager.toggle_point(index)
            if not success:
                self.show_error(f"切换点状态失败: {message}")

        self.update_points_display()

    def move_point_up(self):
        """点上移"""
        selection = self.points_treeview.selection()
        if not selection:
            self.show_warning("请先选择一个点")
            return

        # 只移动第一个选中的点
        item = selection[0]
        index = self.points_treeview.index(item)
        success, message = self.point_manager.move_point_up(index)
        if success:
            self.update_points_display()
            # 保持选中状态
            if index > 0:
                self.points_treeview.selection_set(self.points_treeview.get_children()[index-1])
        else:
            self.show_warning(message)

    def move_point_down(self):
        """点下移"""
        selection = self.points_treeview.selection()
        if not selection:
            self.show_warning("请先选择一个点")
            return

        # 只移动第一个选中的点
        item = selection[0]
        index = self.points_treeview.index(item)
        success, message = self.point_manager.move_point_down(index)
        if success:
            self.update_points_display()
            # 保持选中状态
            if index < len(self.points_treeview.get_children()) - 1:
                self.points_treeview.selection_set(self.points_treeview.get_children()[index+1])
        else:
            self.show_warning(message)

    def duplicate_point(self):
        """复制点"""
        selection = self.points_treeview.selection()
        if not selection:
            self.show_warning("请先选择一个点")
            return

        # 只复制第一个选中的点
        item = selection[0]
        index = self.points_treeview.index(item)
        success, message = self.point_manager.duplicate_point(index)
        if success:
            self.update_points_display()
            self.show_info("点已复制")
        else:
            self.show_error(f"复制点失败: {message}")

    def delete_selected_points(self):
        """删除选中点 - 修复版本"""
        selection = self.points_treeview.selection()
        if not selection:
            self.show_warning("请先选择点")
            return

        if not messagebox.askyesno("确认删除", f"确定要删除选中的 {len(selection)} 个点吗？"):
            return

        # 按索引从大到小删除，避免索引变化
        indices = sorted([self.points_treeview.index(item) for item in selection], reverse=True)

        for index in indices:
            success, message = self.point_manager.delete_point(index)
            if not success:
                self.show_error(f"删除点失败: {message}")

        self.update_points_display()

    def validate_all_points(self):
        """验证所有点"""
        is_valid, errors = self.point_manager.validate_all_points()
        if is_valid:
            self.show_info("所有点验证通过")
        else:
            error_msg = "发现以下问题:\n\n" + "\n".join([f"点 {i+1}: {msg}" for i, msg in errors])
            self.show_error(error_msg)

    def show_points_statistics(self):
        """显示点统计信息"""
        stats = self.point_manager.get_point_statistics()

        stats_text = f"""点统计信息:
        
总点数: {stats['total_points']}
启用点数: {stats['enabled_points']}
禁用点数: {stats['disabled_points']}

点击类型分布:
"""
        for click_type, count in stats['click_type_distribution'].items():
            stats_text += f"  {click_type}: {count}个\n"

        stats_text += f"""
图片点: {stats['image_points']}个
文本点: {stats['text_points']}个
空点: {stats['empty_points']}个
"""
        self.show_info(stats_text, "点统计")

    def import_points(self):
        """导入点"""
        file_path = filedialog.askopenfilename(
            title="选择点文件",
            filetypes=[("点文件", "*.json"), ("所有文件", "*.*")]
        )

        if file_path:
            merge = messagebox.askyesno("导入选项", "是否合并到现有点？\n选择'否'将替换所有现有点。")
            success, message = self.point_manager.import_points(file_path, merge)
            if success:
                self.update_points_display()
                self.show_info(message)
            else:
                self.show_error(message)

    def export_points(self):
        """导出点"""
        if self.point_manager.get_point_count() == 0:
            self.show_warning("没有点可导出")
            return

        file_path = filedialog.asksaveasfilename(
            title="保存点文件",
            defaultextension=".json",
            filetypes=[("点文件", "*.json"), ("所有文件", "*.*")]
        )

        if file_path:
            success, message = self.point_manager.export_points(file_path)
            if success:
                self.show_info(message)
            else:
                self.show_error(message)

    def select_image(self):
        """选择图片 - 修复版本"""
        file_path = filedialog.askopenfilename(
            title="选择图片文件",
            filetypes=[
                ("图片文件", "*.png *.jpg *.jpeg *.gif *.bmp"),
                ("所有文件", "*.*")
            ]
        )

        if file_path and self.image_processor.load_image(file_path):
            self.show_info(f"已选择图片: {self.image_processor.get_image_name()}")
        else:
            self.show_error("图片加载失败")

    def test_input(self):
        """测试输入 - 修复版本"""
        if not self.automation_executor.is_pyautogui_available():
            self.show_error("pyautogui 不可用，无法执行测试")
            return

        # 获取测试配置
        config = {
            'input_method': self.input_method_var.get(),
            'clear_before_input': self.clear_before_input.get(),
            'enter_after_input': self.enter_after_input.get()
        }

        # 在新线程中执行测试
        thread = threading.Thread(target=self._test_input_thread, args=(config,), daemon=True)
        thread.start()

    def _test_input_thread(self, config):
        """测试输入线程"""
        try:
            import pyautogui
            import pyperclip

            self.update_status("测试输入中...")

            if config['input_method'] == "paste":
                test_text = "自动化工具测试文本"
                pyperclip.copy(test_text)
                time.sleep(0.1)
                pyautogui.hotkey('ctrl', 'v')
                self.update_status(f"已测试粘贴输入: '{test_text}'")
            else:
                test_text = "键盘输入测试"
                pyautogui.write(test_text, interval=0.05)
                self.update_status(f"已测试键盘输入: '{test_text}'")

            if config['enter_after_input']:
                time.sleep(0.2)
                pyautogui.press('enter')
                self.update_status("已按回车确认")

        except Exception as e:
            self.show_error(f"测试输入失败: {e}")

    def start_execution(self):
        """开始执行 - 修复版本"""
        if self.is_executing:
            return

        # 检查pyautogui是否可用
        if not self.automation_executor.is_pyautogui_available():
            self.show_error("pyautogui 不可用，无法执行自动化操作\n请安装依赖包：pip install pyautogui")
            return

        # 验证点数据
        is_valid, errors = self.point_manager.validate_all_points()
        if not is_valid:
            error_msg = "执行前验证失败:\n\n" + "\n".join([f"点 {i+1}: {msg}" for i, msg in errors])
            self.show_error(error_msg)
            return

        self.is_executing = True
        self.execute_btn.config(state=tk.DISABLED)
        self.stop_btn.config(state=tk.NORMAL)
        self.record_btn.config(state=tk.DISABLED)

        # 获取配置
        config = {
            'global_delay': float(self.global_delay_var.get()),
            'global_interval': float(self.global_interval_var.get()),
            'input_method': self.input_method_var.get(),
            'clear_before_input': self.clear_before_input.get(),
            'enter_after_input': self.enter_after_input.get(),
            'stop_on_error': self.stop_on_error.get()
        }

        # 在新线程中执行
        thread = threading.Thread(target=self._execution_thread, args=(config,), daemon=True)
        thread.start()

    def _execution_thread(self, config):
        """执行线程 - 修复版本"""
        try:
            self.automation_executor.execute_all_actions(config, self.update_status)
        except Exception as e:
            self.show_error(f"执行过程中出错: {e}")
        finally:
            self._stop_execution()

    def stop_execution(self):
        """停止执行"""
        self.automation_executor.stop_execution()
        self._stop_execution()

    def _stop_execution(self):
        """停止执行后的清理"""
        self.is_executing = False
        self.root.after(0, lambda: self.execute_btn.config(state=tk.NORMAL))
        self.root.after(0, lambda: self.stop_btn.config(state=tk.DISABLED))
        self.root.after(0, lambda: self.record_btn.config(state=tk.NORMAL))

    def open_excel_tool(self):
        """打开Excel工具 - 修复版本"""
        if self.excel_tool_window is None or not self.excel_tool_window.window.winfo_exists():
            self.excel_tool_window = ExcelToolWindow(self.root, self)
        else:
            self.excel_tool_window.window.lift()

    def set_excel_data(self, excel_data: Dict[str, Any]):
        """设置Excel数据（供Excel工具调用）"""
        self.excel_data = excel_data
        if excel_data and 'configs' in excel_data:
            self.excel_execute_btn.config(state=tk.NORMAL)
            self.show_info(f"Excel数据已加载: {len(excel_data.get('data', []))} 行数据")
        else:
            self.excel_execute_btn.config(state=tk.DISABLED)

    def start_excel_execution(self):
        """开始执行Excel数据 - 修复版本"""
        if self.is_excel_executing:
            return

        if not self.excel_data:
            self.show_warning("请先通过Excel工具加载数据")
            return

        # 检查pyautogui是否可用
        if not self.automation_executor.is_pyautogui_available():
            self.show_error("pyautogui 不可用，无法执行自动化操作")
            return

        self.is_excel_executing = True
        self.excel_execute_btn.config(state=tk.DISABLED)
        self.stop_excel_btn.config(state=tk.NORMAL)
        self.record_btn.config(state=tk.DISABLED)

        # 在新线程中执行Excel数据
        thread = threading.Thread(target=self._excel_execution_thread, daemon=True)
        thread.start()

    def _excel_execution_thread(self):
        """Excel数据执行线程"""
        try:
            import pyautogui
            import pyperclip

            data = self.excel_data.get('data', [])
            configs = self.excel_data.get('configs', [])

            if not data or not configs:
                self.show_error("Excel数据不完整")
                return

            total_rows = len(data)
            self.update_status(f"开始执行Excel数据，共 {total_rows} 行")

            # 获取全局配置
            global_delay = float(self.global_delay_var.get())
            global_interval = float(self.global_interval_var.get())

            # 初始延迟
            self.update_status(f"准备执行，等待 {global_delay} 秒")
            time.sleep(global_delay)

            # 执行每一行数据
            for row_index, row_data in enumerate(data):
                if not self.is_excel_executing:
                    break

                self.update_status(f"执行第 {row_index + 1}/{total_rows} 行数据")

                # 执行每个配置项
                for config in configs:
                    if not config.get('enabled', True):
                        continue

                    column_name = config.get('column_name')
                    if column_name and column_name in row_data:
                        value = row_data[column_name]

                        # 根据配置执行相应的操作
                        if config.get('input_method') == 'image':
                            # 图片输入
                            if os.path.exists(str(value)):
                                if self.image_processor.copy_image_to_clipboard(str(value)):
                                    time.sleep(0.3)
                                    pyautogui.hotkey('ctrl', 'v')
                                    time.sleep(0.5)
                        else:
                            # 文本输入
                            if config.get('clear_before_input', True):
                                pyautogui.hotkey('ctrl', 'a')
                                time.sleep(0.2)
                                pyautogui.press('backspace')
                                time.sleep(0.1)

                            if config.get('input_method') == 'paste':
                                pyperclip.copy(str(value))
                                time.sleep(0.1)
                                pyautogui.hotkey('ctrl', 'v')
                            else:
                                pyautogui.write(str(value), interval=0.05)

                            if config.get('enter_after_input', False):
                                time.sleep(0.2)
                                pyautogui.press('enter')

                        # 配置项之间的间隔
                        time.sleep(float(config.get('delay_after', 0.5)))

                # 行之间的间隔
                if row_index < total_rows - 1:
                    time.sleep(global_interval)

            if self.is_excel_executing:
                self.update_status(f"Excel数据执行完成，共 {total_rows} 行")
                self.show_info(f"Excel数据执行完成，共 {total_rows} 行")
            else:
                self.update_status("Excel数据执行已停止")

        except Exception as e:
            self.show_error(f"执行Excel数据时出错: {e}")
        finally:
            self._stop_excel_execution()

    def stop_excel_execution(self):
        """停止Excel数据执行"""
        self.is_excel_executing = False
        self._stop_excel_execution()

    def _stop_excel_execution(self):
        """停止Excel执行后的清理"""
        self.is_excel_executing = False
        self.root.after(0, lambda: self.excel_execute_btn.config(state=tk.NORMAL))
        self.root.after(0, lambda: self.stop_excel_btn.config(state=tk.DISABLED))
        self.root.after(0, lambda: self.record_btn.config(state=tk.NORMAL))

    def save_config(self):
        """保存配置 - 修复版本"""
        config = {
            'always_on_top': self.always_on_top_var.get(),
            'click_type': self.click_type_var.get(),
            'delay_after': float(self.delay_after_var.get()),
            'input_method': self.input_method_var.get(),
            'clear_before_input': self.clear_before_input.get(),
            'enter_after_input': self.enter_after_input.get(),
            'stop_on_error': self.stop_on_error.get(),
            'global_delay': float(self.global_delay_var.get()),
            'global_interval': float(self.global_interval_var.get()),
            'auto_save_config': self.auto_save_var.get()
        }

        # 合并窗口位置
        config.update(self.config)

        if self.config_manager.save_config(config):
            self.config = config
            self.show_info("配置已保存")
        else:
            self.show_error("配置保存失败")

    def show_help(self):
        """显示帮助信息"""
        help_text = """屏幕点击和输入工具 - 使用说明

基本操作:
• Ctrl+R: 开始记录点
• Ctrl+E: 执行所有操作
• Ctrl+S: 停止执行
• Delete: 删除选中点
• F1: 显示帮助

记录模式:
1. 点击"记录点"或按Ctrl+R进入记录模式
2. 将鼠标移动到目标位置
3. 按空格键记录点
4. 输入相关文本（可选）
5. 按ESC退出记录模式

配置说明:
• 点击类型: 单击、双击或右键点击
• 输入方式: 粘贴、键盘输入或图片输入
• 延迟设置: 控制操作之间的等待时间

高级功能:
• Excel工具: 批量处理Excel数据
• 点管理: 导入/导出点配置
• 验证功能: 检查点数据的有效性

注意事项:
• 确保目标应用程序窗口可见
• 在执行过程中不要移动鼠标
• 建议先进行测试输入
"""
        self.show_info(help_text, "使用帮助")

    def _check_recording_dependencies(self):
        """检查记录功能所需的依赖"""
        try:
            import pyautogui
            import keyboard
            return True
        except ImportError as e:
            missing_module = str(e).split(" ")[-1]
            if "keyboard" in missing_module:
                self.show_error(
                    "缺少键盘监听依赖库\n\n"
                    "请安装 keyboard 库：\n"
                    "pip install keyboard\n\n"
                    "或者使用完整依赖安装：\n"
                    "pip install keyboard pyautogui"
                )
            else:
                self.show_error(f"缺少必要的依赖库: {missing_module}")
            return False

    def show_info(self, message: str, title: str = "信息"):
        """显示信息对话框"""
        self.root.after(0, lambda: messagebox.showinfo(title, message))

    def show_warning(self, message: str, title: str = "警告"):
        """显示警告对话框"""
        self.root.after(0, lambda: messagebox.showwarning(title, message))

    def show_error(self, message: str, title: str = "错误"):
        """显示错误对话框"""
        self.root.after(0, lambda: messagebox.showerror(title, message))

    def on_closing(self):
        """窗口关闭事件 - 修复版本"""
        try:
            # 保存配置
            if self.auto_save_var.get():
                self.save_config()

            # 停止所有执行
            if self.is_executing:
                self.stop_execution()
            if self.is_excel_executing:
                self.stop_excel_execution()

            # 清理资源
            self.image_processor.clear_image()
            self.excel_handler.clear_data()

            # 关闭窗口
            self.root.destroy()

        except Exception as e:
            logger.error(f"关闭窗口时出错: {e}")
            self.root.destroy()


if __name__ == "__main__":
    # 测试代码
    import logging
    logging.basicConfig(level=logging.INFO)

    root = tk.Tk()
    config_manager = ConfigManager()
    app = MainWindow(root, config_manager)
    root.mainloop()